package main

import (
	"context"
	"google.golang.org/grpc"
	"google.golang.org/grpc/codes"
	"google.golang.org/grpc/status"
	pb "grpc-demo/complex/proto"
	"log"
	"net"
	"runtime"
	"time"
)

// server.go需要完成以下2个部分
// 实现我们服务定义的生成的服务接口：做我们的服务的实际的“工作”。
// 运行一个 gRPC 服务器，监听来自客户端的请求并返回服务的响应。

// 1. 简单grpc
// SimpleServer is the server API for Simple service.
// 实现SimpleServer
type SimpleService struct {
	pb.UnimplementedSimpleServer
}

// 当请求超时后，服务端应该停止正在进行的操作，避免资源浪费。

// 实现Route方法
func (s *SimpleService) Route(ctx context.Context, req *pb.SimpleRequest) (*pb.SimpleResponse, error) {
	data := make(chan *pb.SimpleResponse)
	go handle(ctx, req, data)
	select {
	case res := <-data:
		return res, nil
	case <-ctx.Done():
		return nil, status.Errorf(codes.Canceled, "client cancelled, abandoning")
	}
}

// 单向channel，发送语句
func handle(ctx context.Context, req *pb.SimpleRequest, data chan<- *pb.SimpleResponse) {
	select {
	case <-ctx.Done():
		log.Println(ctx.Err())
		runtime.Goexit() // 超时后退出该协程
	case <-time.After(time.Second * 4): // 模拟耗时操作
		res := pb.SimpleResponse{
			Code:  200,
			Value: "hello " + req.Data,
		}
		data <- &res
	}
}

func main() {
	log.SetFlags(log.Llongfile)
	// 监听本地端口
	listener, err := net.Listen("tcp", ":8000")
	if err != nil {
		log.Fatal(err)
	}
	defer listener.Close()

	// 新建grpc服务实例
	grpcServer := grpc.NewServer()

	// 在gRPC服务器注册我们的服务
	pb.RegisterSimpleServer(grpcServer, &SimpleService{})

	log.Println(":8000 is listening")
	//用服务器 Serve() 方法以及我们的端口信息区实现阻塞等待，后面的代码无法执行，直到进程被杀死或者 Stop() 被调用
	err = grpcServer.Serve(listener)
	if err != nil {
		log.Fatal(err)
	}
}
